package com.init.iblog.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.init.iblog.constants.SystemConstants;
import com.init.iblog.domain.ResponseResult;
import com.init.iblog.domain.dto.BlogDto;
import com.init.iblog.domain.entity.Blog;
import com.init.iblog.domain.entity.BlogTag;
import com.init.iblog.domain.entity.Category;
import com.init.iblog.domain.entity.Tag;
import com.init.iblog.domain.vo.BlogPage;
import com.init.iblog.domain.vo.PageVo;
import com.init.iblog.domain.vo.BlogDetailVo;
import com.init.iblog.domain.vo.HotBlogVo;
import com.init.iblog.mapper.BlogMapper;
import com.init.iblog.service.BlogService;
import com.init.iblog.service.BlogTagService;
import com.init.iblog.service.CategoryService;
import com.init.iblog.utils.BeanCopyUtils;
import com.init.iblog.utils.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements BlogService {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private BlogTagService blogTagService;

    @Autowired(required = false)
    private BlogMapper blogMapper;
    /**
     * 查询热门文章
     * 查询条件：必须时正式文章、按照浏览量进行排序、最多只能查询出10条博客
     * @return
     */
    @Override
    public ResponseResult hotBlogList() {


        //LambdaQueryWrapper可封装查询条件
        LambdaQueryWrapper<Blog> queryWrapper = new LambdaQueryWrapper<>();
        //必须是正式文章（Status字段   状态-->   0：已发布，1：草稿）
        queryWrapper.eq(Blog::getStatus, SystemConstants.BLOG_STATUS_NORMAL);
        //按照浏览量进行排序(ViewCount字段   浏览量)
        queryWrapper.orderByDesc(Blog::getViewCount);
        //最多只能查询出10条博客
        Page<Blog> page = new Page(1,10);
        page(page,queryWrapper);
        //getRecords()方法获取数据
        List<Blog> blogList = page.getRecords();
        System.out.println(blogList.toString());

        //bean拷贝：将查询后的blogList内的数据拷贝至热门文章视图类(HotBlogVo)中
        //Spring框架下有相关类
//        List<HotBlogVo> hotBlogVos = new ArrayList<>();
//        for (Blog blog : blogList) {
//            HotBlogVo hotBlogVo = new HotBlogVo();
//            BeanUtils.copyProperties(blog,hotBlogVo);
//            hotBlogVos.add(hotBlogVo);
//        }
        //使用工具类进行拷贝
        List<HotBlogVo> hotBlogVos = BeanCopyUtils.copyBeanList(blogList, HotBlogVo.class);
        System.out.println(hotBlogVos.toString());
        return ResponseResult.okResult(hotBlogVos);
    }


    /**
     * 分页查询博客列表
     * @param pageNum
     * @param pageSize
     * @param categoryId
     * @return
     */
    @Override
    public ResponseResult blogListPage(Integer pageNum, Integer pageSize, Long categoryId) {

        //查询条件
        LambdaQueryWrapper<Blog> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        //如果有categoryId（即分类查询发来的请求）   查询时需和传入的相同
        //condition为条件，当条件为true时，即将后面的条件加入查询条件中，当condition条件为false时，则不将后面的条件加入查询条件中
        //condition条件：当categoryId不为空且categoryId值大于0
        lambdaQueryWrapper.eq(Objects.nonNull(categoryId)&&categoryId>0,Blog::getCategoryId,categoryId);
        //博客是正式发布的
        lambdaQueryWrapper.eq(Blog::getStatus,SystemConstants.BLOG_STATUS_NORMAL);
        //对isTop进行降序
        lambdaQueryWrapper.orderByDesc(Blog::getIsTop);
        //分页查询
        Page<Blog> page = new Page<>(pageNum,pageSize);
        page(page,lambdaQueryWrapper);

        //查询categoryName
        //获取博客列表
        List<Blog> blogs = page.getRecords();
        //使用categoryId去查询categoryName进行设置

        //使用循环进行实现
//        for (Blog blog: blogs) {
//            Category category = categoryService.getById(blog.getCategoryId());
//            blog.setCategoryName(category.getName());
//        }

        //stream流方式实现
        blogs.stream()
                .map(new Function<Blog, Blog>() {
                    @Override
                    public Blog apply(Blog blog) {
                        //获取分类id,查询分类信息，获取分类名称
                        Category category = categoryService.getById(blog.getCategoryId());
                        String name = category.getName();
                        blog.setCategoryName(name);
                        return blog;
                    }
                }).collect(Collectors.toList());

        //封装查询结果
        List<BlogPage> blogPage = BeanCopyUtils.copyBeanList(page.getRecords(), BlogPage.class);
        PageVo blogPageVo = new PageVo(blogPage,page.getTotal());
        return ResponseResult.okResult(blogPageVo);
    }

    /**
     * 根据博客id查询博客详情
     * @param id
     * @return
     */
    @Override
    public ResponseResult getBlogDetail(Long id) {
        //根据id查询博客
        Blog blog = getById(id);

        //从redis中获取viewCount
        Integer viewCount = redisCache.getCacheMapValue(SystemConstants.BLOG_VIEW_COUNT, id.toString());
        blog.setViewCount(viewCount.longValue());
        //转化为VO
        final BlogDetailVo blogDetailVo = BeanCopyUtils.copyBean(blog, BlogDetailVo.class);
        //根据分类id查询分类名
        Long categoryId = blogDetailVo.getCategoryId();
        Category category = categoryService.getById(categoryId);
        if(category != null){
            blogDetailVo.setCategoryName(category.getName());
        }
        //封装响应对象
        return ResponseResult.okResult(blogDetailVo);
    }


    /**
     * 更新博客浏览量
     * @param id
     * @return
     */
    @Override
    public ResponseResult updateViewCount(Long id) {

        //更新redis中的对应id博客的浏览量
        redisCache.incrementCacheMapValue(SystemConstants.BLOG_VIEW_COUNT,id.toString(),1);
        return ResponseResult.okResult();
    }


    /**
     * 添加Blog
     * @param blogDto
     * @return
     */
    @Override
    @Transactional   //添加事务回滚
    public ResponseResult addArticle(BlogDto blogDto) {

        //添加 博客
        Blog blog = BeanCopyUtils.copyBean(blogDto, Blog.class);
        save(blog);


        List<BlogTag> blogTags = blogDto.getTags().stream()
                .map(tagId -> new BlogTag(blog.getId(), tagId))
                .collect(Collectors.toList());

        //添加 博客和标签的关联
        blogTagService.saveBatch(blogTags);
        return ResponseResult.okResult();
    }

    /**
     * 分页查询文章列表(带条件查询)
     * @param pageNum
     * @param pageSize
     * @param title
     * @param summary
     * @return
     */
    @Override
    public ResponseResult getArticleListPage(Integer pageNum, Integer pageSize, String title, String summary) {
        LambdaQueryWrapper<Blog> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //若有title和summary则按条件查询(封装查询条件)
        lambdaQueryWrapper.eq(Objects.nonNull(title),Blog::getTitle,title);
        lambdaQueryWrapper.eq(Objects.nonNull(summary),Blog::getSummary,summary);
        lambdaQueryWrapper.eq(Blog::getStatus,SystemConstants.BLOG_STATUS_NORMAL);
        //分页查询
        Page<Blog> page = new Page<>(pageNum,pageSize);
        page(page,lambdaQueryWrapper);

        //封装查询结果
        List<BlogPage> blogPages = BeanCopyUtils.copyBeanList(page.getRecords(),BlogPage.class);
        PageVo blogPageVo = new PageVo(blogPages,page.getTotal());

        return ResponseResult.okResult(blogPageVo);
    }

    /**
     * 获取文章详情
     * @param id
     * @return
     */
    @Override
    public ResponseResult getArticleDetail(Long id) {
        //根据id查询博客
        Blog blog = getById(id);
        BlogDto blogDto = BeanCopyUtils.copyBean(blog, BlogDto.class);

        System.out.println("+++++++++++前端传来的参数博客id"+id);

        //查询标签id
        LambdaQueryWrapper<BlogTag> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BlogTag::getBlogId,id);
        List<BlogTag> tags = blogTagService.list(queryWrapper);
        System.out.println("++++++++++++查询结果"+tags.toString());
        List<Long> tagIds = new ArrayList<Long>();
        int i = 0;
        for (BlogTag t:tags) {
            i++;
            System.out.println("=======第"+ i+ "次进入循环");
            System.out.println("++++++++++++进入循环，打印tag"+ t.toString());
            System.out.println("+++++++t.getTagId()的值为  "+ t.getTagId());
            tagIds.add(t.getTagId());
        }
        blogDto.setTags(tagIds);
        return ResponseResult.okResult(blogDto);
    }

    /**
     * 更新文章
     * @param blogDto
     * @return
     */
    @Override
    public ResponseResult updateArticle(BlogDto blogDto) {
        //添加 博客
        Blog blog = BeanCopyUtils.copyBean(blogDto, Blog.class);
        updateById(blog);
        List<BlogTag> blogTags = blogDto.getTags().stream()
                .map(tagId -> new BlogTag(blog.getId(), tagId))
                .collect(Collectors.toList());
        //删除博客更新前中间表对应的记录
        blogTagService.deleteBlogTag(blog.getId());
        //添加新的博客所对应的标签id到中间表中
        //添加 博客和标签的关联
        blogTagService.saveBatch(blogTags);
        return ResponseResult.okResult();
    }


    /**
     * 删除博客
     * @param id
     * @return
     */
    @Override
    public ResponseResult deleteArticle(Long id) {
        //删除blog表内的数据
        blogMapper.deleteById(id);


        //删除中间表blogTag表内数据
        blogTagService.deleteBlogTag(id);
        return ResponseResult.okResult();
    }
}
